// T extends Function 判断这个T 是函数类型, 也可以 T extends (...arg: any[]) => infer R; 这里的R 就是推断出函数的返回类型
type Return<T> = T extends (...arg: any[]) => infer R ? R : T;

type sum = (a: number, b: number) => number;

// const aa: sum = 123;

type concat = (a: any[], b: any[]) => any[];

// ReturnType 可以得到函数的返回类型，现在要实现这个 ReturnType
let sumResult: ReturnType<sum>;
let concatResult: ReturnType<concat>;

let mySumResult: Return<sum>;
let myConcatResult: Return<concat>;

// infer 实例 2
type PromiseType<T> = T extends Promise<infer R> ? PromiseType<R> : T;
type PromiseType1<T> = T extends Promise<infer R> ? R : T;

type mpt = PromiseType1<Promise<number>>;
type mpt2 = PromiseType<Promise<Promise<string>>>;

type pt = PromiseType<Promise<string>>; // 希望得到 string
type nt = PromiseType<Promise<Promise<number>>>; // 希望得到 number

// infer 实例3, FirstArg 接收一个函数，得到该函数每一个入参的类型
type FirstArg<T> = T extends (first: infer K, ...arg: any[]) => any ? K : T;
type getFirstArg = FirstArg<(a: number, b: number, d: any[]) => void>;

type getFirstArg2 = FirstArg<() => void>;

// infer 实例4 ，得到数组中每个项的类型

type ArrayType<T> = T extends (infer K)[] ? K : T;

type ItemType1 = ArrayType<string[]>; // string

type ItemType2 = ArrayType<[string, number, object, string[], symbol]>; // string | number | object | string[]

// const aa: number[] = [123, 3, 4];

type MyArrType = [number, string, string];

type ItmeType3 = ArrayType<MyArrType>;

const myArrType = [123, "mmm", "mmmmmmm"];

const myAa = 123123;

myArrType.push(234);
